package capstone.tagit;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.Toast;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;

/**
 * 
 * TagsList is an overlay over the map containing the tags as overlay items.
 * The list of tags to be displayed on screen, as well as extra tags stored as backup.
 * Handles tag filtering and the operation to be performed upon tapping a tag.
 * Also contains a method for adding a tag in order into a list of tags (currently in O(n) time).
 * This class does not yet handle any cleanup operations, which should be added.
 *
 */
public class TagsList extends ItemizedOverlay<Tag>
{
	/**
	 * The ordered list of Tags currently displayed on screen.  Ordered based on
	 * the TagComparator class.
	 */
	private LinkedList<Tag> mOverlays = new LinkedList<Tag>();
	/**
	 * The list of all tags stored in program memory.  Includes tags on screen and off.
	 * Ordered based on the TagComparator class.
	 */
	private LinkedList<Tag> mOverlaysBackup = new LinkedList<Tag>();
	/**
	 * The list of TagTypes currently not displayed on screen.
	 */
	private LinkedList<TagType> tagsOut = new LinkedList<TagType>();
	/**
	 * The parent Context in which this Overlay is instantiated.  In this case, TagItMapActivity.
	 */
	private Context mContext;
	/**
	 * A comparator for tags.  Comes from the TagComparator class.
	 * Tags are sorted by this comparator.
	 */
	Comparator<Tag> compare;
	
	/**
	 * The public constructor for a TagsList object.
	 * Initializes options.
	 * Populates the ItemizedOverlay in order to prepare it for 
	 * adding tags.
	 * @param defaultMarker The default marker object.  It does not particularly
	 * matter what this is, as long as it is one of the markers used by the map app.
	 * @param context The parent context.  In this case, TagItMapActivity.
	 */
	public TagsList(Drawable defaultMarker, Context context)
	{
		super(boundCenterBottom(defaultMarker));
		compare = new TagComparator();
		mContext = context;
		populate();
	}
	
	/**
	 * Adds a Tag into the Overlay.  Will be added to Backup and to
	 * the onscreen list if it's TagType is currently active.
	 * @param overlay	The Tag to be added to the list.
	 * @return	True if the tag was not already found in the list.
	 */
	public boolean addOverlay(Tag overlay)
	{
		boolean rVal = addTagToList(mOverlaysBackup,overlay);
		if (!tagsOut.contains(overlay.getType())){
			addTagToList(mOverlays,overlay);
		}
		populate();
		return rVal;
	}
	
	/**
	 * Filtes out a TagType.  Adds the type to the tagsOut list.
	 * Actual filtering of the tags themselves takes place in filterList.
	 * @param type	The type to be removed from display
	 */
	public void filterOutType(TagType type){
		if (!tagsOut.contains(type)){
			tagsOut.add(type);
		}
	}
	
	/**
	 * Filters in a TagType.  Removes the type from the tagsOut list, if it is in it.
	 * Actual filtering of the tags themselves takes place in filterList.
	 * @param type	The type to be added back to display.
	 */
	public void filterInType(TagType type){
		if (tagsOut.contains(type)){
			tagsOut.remove(type);
		}
	}

	/**
	 * Filters the tags based on the current contents of TagsOut.
	 * Instantiates mOverlays as a new List, then adds all the Tags in mOverlaysBackup that
	 * are of a type not filtered out.
	 */
	public void filterList(){
		mOverlays = new LinkedList<Tag>();
		for (Tag check : mOverlaysBackup){
			if (!tagsOut.contains(check.getType())){
				mOverlays.add(check);  // does not use the sorting add method because backup is already sorted
			}
		}
		populate();
	}
	
	/**
	 * Because TagsList is a subclass of ItemizedOverlay, it needs
	 * this method.
	 * createItem is called from populate() to get the items to add
	 * on screen.
	 */
	protected Tag createItem(int i)
	{
		try{
			return mOverlays.get(i);
		}catch(IndexOutOfBoundsException e){
			return null;
		}
	}

	@Override
	public int size()
	{
		return mOverlays.size();
	}
	@Override
	/**
	 * onTap defines what to do when a user taps a tag.
	 * Currently displays a little information in a toast.
	 */
	protected boolean onTap(int index)
	{
		if (mOverlays.isEmpty()){
			return false;
		}
		Tag item = mOverlays.get(index);
		Toast.makeText(mContext,
				item.getTitle()+"\n"+ item.getSnippet() + "\n" + item.getDate().toString(),
				Toast.LENGTH_SHORT).show();
		return true;
	}
	@Override
	public boolean onTouchEvent(android.view.MotionEvent event,
                            MapView mapView){
		if (mOverlays.isEmpty()){
			return false;
		}
		else{
			return super.onTouchEvent(event, mapView);
		}
	}
	/**
	 * Inserts Tags in order into an ordered list.
	 * Ordering is based on the TagComparator.
	 * Also indicates duplicate tags, which is used to prevent getting the same tags
	 * multiple times from the server.
	 * 
	 * This method needs to do something smarter it comp returns that the two tags are "equal".
	 * Currently, it will treat them as duplicates, but it is quite possible that two tags of the same
	 * "priority level" could be different tags.
	 * 
	 * @param list The list into which to insert the tag
	 * @param tag The tag to insert
	 * @return true if the tag is added to the list, false if it is a duplicate
	 */
	private boolean addTagToList(List<Tag> list, Tag tag){
		ListIterator<Tag> listIter = list.listIterator();
		while(listIter.hasNext()){
			int comp = compare.compare(listIter.next(),tag);
			if (comp < 0){
				continue;
			}
			else if (comp == 0){
				return false;
			}
			else{
				listIter.previous();
				listIter.add(tag);
				return true;
			}
		}
		listIter.add(tag);
		return true;
	}
}